        SUBT    > Sources.FSUtils2 - Delete

 [ haswipe
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;                      W i l d c a r d   D e l e t i o n
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeEntry
; =========

; In    r1 -> path to delete
;       r3 = bitset for delete
;       r4,r5 = optional time (start)
;       r6,r7 = optional time (end)

WipeEntry NewSwiEntry "r0-r10",utils    ; WipeWildObject may destroy all regs
                                        ; Extra large frame for utils

 [ debugwipe
        DLINE   "FSControl_Wipe: options '",cc
        TST     r3, #util_confirm
        BEQ     %FT01
        DLINE   "C", cc
01
        TST     r3, #util_force
        BEQ     %FT01
        DLINE   "F", cc
01
        TST     r3, #util_recurse
        BEQ     %FT01
        DLINE   "R", cc
01
        TST     r3, #util_verbose
        BEQ     %FT01
        DLINE   "V", cc
01
        DREG r3,"' "
 ]
        BL      Util_CommonStart
        BVS     %FA99 ; SwiExit - Nothing allocated
        MOV     r8, #0                  ; No second file

        BL      WipeWildObject

        BL      Util_FreeFileStrings_R7 ; Catch errors from these on SwiExit
                                        ; 'Cos it's nice to print ...
 [ Version >= 170
        ; Now freed in Util_CommonStart
 |
        BL      SFreePassedFilenameAndSpecial ; Ditto
 ]

        LDR     r14, globalerror        ; Give 'Not found' if no error below
        CMP     r14, #0                 ; fp is valid, of course ...
        LDREQ   r14, util_ndir          ; and no dirs or files deleted
        CMPEQ   r14, #0
        LDR     r0, util_nfiles         ; r0 useful for below - load always !
        CMPEQ   r0, #0
        LDREQ   r14, util_nskipped      ; Only give error if complete wally
        CMPEQ   r14, #0
        BEQ     %FA98

        LDR     r14, util_bitset
        TST     r14, #util_verbose
        ADR     r1, fsw_files_deleted
        BLNE    Util_FilesDone          ; Say '20 files deleted'

90      BLVS    CopyErrorExternal

99
        SwiExit


98      addr    r0, ErrorBlock_NothingToDelete
        BL      CopyError
        B       %BT99


fsw_files_deleted
        DCB     "CW4", 0
        DCB     "CW8", 0
        DCB     "CW9", 0
        DCB     "CW10", 0
                          ALIGN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeWildObject
; ==============

; src *: WipeObject on all that match
; src -: WipeObject given name

; Out   Only r7, wp preserved

WipeWildObject ENTRY

 [ debugwipe
 DLINE "WipeWildObject"
 ]
        LDR     r1, [r7, #copy_leafname] ; If not wild, do single deletion
        BL      Util_CheckWildName
        BNE     %FT90                   ; Single deletion

; ...................... Wild object spec for delete ..........................

        MOV     r9, r1                  ; Remember current leafname

        MOV     r14, #0                 
        STR     r14, util_direntry      ; Start at the beginning of dir
        STR     r14, [r7, #copy_leafname] ; 'Free' leafname !

10 ; Loop over names, match against wildcard. Leafname NewString'ed each time
   ; round loop; fullname explicitly made and freed

        BL      STestEscape             ; Util grade, not copied
        BLVS    CopyErrorExternal
        BLVC    Util_ReadDirEntry       ; Get a name. Uses + updates util_diren
        BVS     %FT60                   ; Put old leafname back, exit

        CMP     r3, #0                  ; No name xferred ?
        BEQ     %FT60                   ; Means eod

        ADR     r4, util_objectname     ; What we read just now
 [ debugwipe
        DSTRING r4, "util_objectname for WipeWildObject = "
 ]
        STR     r4, [r7, #copy_leafname] ; Use as source leafname if matches
        BL      Util_TryMatch
        BNE     %BT10                   ; Loop - try another name

        MOV     r0, r7                  ; Create fullname of each object
        BL      Util_AppendLeafToDir    ; that matched wildcard
        BVS     %FT60                   ; Put old leafname back, exit

        Push    r9                      ; Preserve wild pattern round call
        BL      WipeObject
        Pull    r9

        LDR     r2, [r7, #copy_name]    ; Deallocate new fullname always
        BL      SFreeArea               ; Accumulate V from Wipe/Free
        BVC     %BT10                   ; Loop - try another name
   
60      STR     r9, [r7, #copy_leafname] ; Put old leafname back
        EXIT


; .......... Single object deletion. Must read object info ourselves ..........

; NB. Don't call WipeObject - if deleting dir, just recurse one level unless
; punter wants more than that

90      MOV     r0, r7                  ; Create fullname of object
        BL      Util_AppendLeafToDir    ; from existing (non-wild) leafname
        EXIT    VS

        BL      Util_SingleObjectSetup  ; Error if not found
        BVS     %FT95                   ; Deallocate error
        LDR     lr, util_objecttype
        TEQ     lr, #object_directory
        BEQ     %FT96                   ; Is it a dir ?
        BL      WipeFile                ; If it's a file or partition

95      LDR     r2, [r7, #copy_name]    ; Deallocate fullname
        BL      SFreeArea               ; Accumulate V from Wipe/Free
        EXIT


96      BL      WipeDirectory
        B       %BT95

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeObject
; ==========
;
; Delete object, recursing as necessary/required
; Dirname set up for this level
; Leafname already set up after possible wildcard match
; Fullname = dirname + leafname set up

; In    r7 = source file desc^

; Out   r0-r5 corrupted by calls
;       VC: object deleted, skipped by user, date, or dir & ~recurse
;       VS: failed in deletion, or aborted

WipeObject ENTRY

 [ debugwipe
 DLINE "WipeObject"
 ]
        LDR     r14, util_objecttype    ; What is it ?

        ; Partitions get treated like files
        TEQ     r14, #object_directory
        BEQ     %FT50

; Wipe existing file

        BL      WipeFile
        EXIT


50 ; It's a directory. Are we recursing ?

        LDR     r14, util_bitset        ; Recurse set ?
        TST     r14, #util_recurse
        BEQ     %FT70                   ; [no - remember r14 ok]

; Wipe this dir, recursing

        BL      WipeDirectory           ; dir & recurse
        EXIT


70      TST     r14, #util_verbose      ; dir & ~recurse. No need to INC skippd
        EXIT    EQ

        addr    r2, fsw_space_is_a_dir
        BL      Util_PrintNameNL
        BLVS    CopyErrorExternal
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeFile
; ========
;
; Wipe single file (which exists)
; Fullname set up in desc^.name; info read

; In    r7 = file desc^, file exists

; Out   r0, r5 corrupt
;       VC: file deleted, or skipped
;       VS: failed to delete file, or aborted

WipeFile ENTRY

 [ debugwipe
 DLINE "WipeFile"
 ]
        LDR     r14, util_attr          ; If locked & ~force, don't present
        TST     r14, #locked_attribute  ; for deletion
        BEQ     %FT10
        LDR     r14, util_bitset
        TST     r14, #util_force
        BEQ     %FT90                   ; Tell punter we're ignoring it

10      BL      WipeFile_Confirm        ; Ask the punter
        EXIT    VS
        BLNE    Util_IncrementSkipped
        EXIT    NE                      ; Don't delete this file

        LDR     r5, util_attr
        TST     r5, #locked_attribute   ; Is it locked ?
 [ Version >= 170
        MOVNE   r0, #fsfile_WriteInfo   ; Keep other attributes, except attr, unchanged
        LDRNE   r2, util_load
        LDRNE   r3, util_exec
        MOVNE   r5, #read_attribute :OR: write_attribute ; Take out
                                        ;attributes, esp L (non-0 to get
                                        ; around some FSs taking no write to
                                        ; mean locked)
 |
        MOVNE   r5, #0                  ; Take out all attributes, esp L
        MOVNE   r0, #fsfile_WriteAttr   ; attr := r5
 ]
        BLNE    CallFSFile_Given_R7     ; Only if neccessary

50      MOVVC   r0, #fsfile_Delete
        BLVC    CallFSFile_Given_R7

        BLVC    Util_DecrementDirEntry  ; Must go back one in the dir, 'cos
                                        ; we've just deleted the one we read

        BLVC    WipeFile_Verbose        ; Tell them copy action is complete
        EXIT

90      BL      Util_IncrementSkipped
        BL      WipeFile_VerboseLocked  ; locked & ~force
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeDirectory
; =============

; Wipe whole directory contents then delete the directory itself
; Fullname of dir set up in desc^.name; info read

; In    r7 = dir desc^, directory exists

; Out   r0-r5 corrupt
;       VC: directory deleted, or skipped
;       VS: failed to delete directory, or aborted

WipeDirectory ENTRY

 [ debugwipe
 DLINE "WipeDirectory"
 ]
        BL      WipeDirectory_ConfirmAll
        EXIT    VS
        BLNE    Util_IncrementSkipped
        EXIT    NE

; Delete contents of dir, saving quite a bit of info on stack

        BL      Util_IntoDirectory
        BL      WipeWildObject
        BL      Util_OutOfDirectory
        EXIT    VS

; Contents deleted, shall we now delete the dir itself ?

        LDR     r1, [r7, #copy_name]
        BL      Util_SpecialDir
        EXIT    EQ                      ; VClear. Don't try to delete $ etc

        LDR     r5, util_attr
        TST     r5, #locked_attribute   ; If locked & ~force, don't present
        BEQ     %FT70                   ; for deletion
        LDR     r14, util_bitset
        TST     r14, #util_force
        BEQ     %FT90

70      CMP     r0, #0                  ; Did we skip any in there ? VClear
        BLEQ    WipeDirectory_ConfirmDir ; Mustn't try to delete (not empty)
        EXIT    VS                      ; And note that we've had to skip at
        BLNE    Util_IncrementSkipped   ; this level too !
        EXIT    NE

        TST     r5, #locked_attribute   ; Is it locked ?
        MOVNE   r0, #fsfile_WriteInfo
        LDRNE   r2, util_load
        LDRNE   r3, util_exec
        MOVNE   r5, #read_attribute :OR: write_attribute
        BLNE    CallFSFile_Given_R7     ; Only if neccessary

        MOVVC   r0, #fsfile_Delete
        BLVC    CallFSFile_Given_R7

        BLVC    Util_DecrementDirEntry  ; Must go back one in the dir, 'cos
                                        ; we've just deleted the one we read

        BLVC    WipeDirectory_Verbose   ; Tell them delete dir complete
        EXIT

90      BL      Util_IncrementSkipped
        CMP     r0, #0                  ; Did we skip any in there ? VClear
                                        ; Don't give 'xxx is locked' if so
        BLEQ    WipeFile_VerboseLocked  ; locked & ~force
        EXIT

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeFile_Confirm
; ================

; If dates allow deletion, maybe ask punter if he wants to do it

; Out   VS: error
;       VC, EQ -> do it
;       VC, NE -> don't do it

fsw_delete_file         DCB     "CW1", 0
fsw_delete_directory    DCB     "CW2", 0
        ALIGN

WipeFile_Confirm ENTRY "r0, r1, r2"

        BL      Util_DateRange          ; See if dates allow it
        EXIT    NE

        addr    r2, fsw_delete_file

10      LDR     r14, util_bitset        ; Entered from below
        TST     r14, #util_confirm
        EXIT    EQ

        BL      Util_PrintName
        BLVC    Util_GetConfirm
        BLVS    CopyErrorExternal
        EXIT

; .............................................................................
;
; WipeDirectory_ConfirmAll
; ========================

; Out   VS: error
;       VC, EQ -> do it
;       VC, NE -> don't do it

WipeDirectory_ConfirmAll ALTENTRY

        ADR     r2, fsw_contents_of_dir_space
        B       %BT10

; .............................................................................
;
; WipeDirectory_ConfirmDir
; ========================

; Out   VS: error
;       VC, EQ -> do it
;       VC, NE -> don't do it

WipeDirectory_ConfirmDir ALTENTRY

        addr    r2, fsw_delete_directory
        B       %BT10


fsw_contents_of_dir_space DCB   "CW3", 0
fsw_space_is_locked_nl    DCB   "CW5", 0

        ALIGN

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeFile_Verbose
; ================

; Deleted the file, so print copied info if being verbose. nfiles++

; Out   VS: error

fsw_file_deleted        DCB     "CW0", 0        ; File %0 deleted
fsw_directory_deleted   DCB     "CW6", 0        ; Directory %0 deleted

WipeFile_Verbose ENTRY "r0,r2"

        BL      Util_IncrementFiles_TestVerbose
        EXIT    EQ                      ; EQ -> ~verbose

        addr    r2, fsw_file_deleted

50
        BL      Util_PrintNameNL
        BLVS    CopyErrorExternal
        EXIT

; .............................................................................
;
; WipeDirectory_Verbose
; =====================

; Deleted the directory, so print info if being verbose

; Out   VS: error

WipeDirectory_Verbose ALTENTRY

        BL      Util_IncrementDir_TestVerbose
        EXIT    EQ                      ; EQ -> ~verbose

        addr    r2, fsw_directory_deleted
        B       %BT50

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; WipeFile_VerboseLocked
; ======================

; Didn't delete object because it's locked & ~force

; Out   VS: error

WipeFile_VerboseLocked ENTRY "r0,r2"

        LDR     r14, util_bitset
        TST     r14, #util_verbose
        EXIT    EQ

        addr    r2, fsw_space_is_locked_nl
        BL      Util_PrintNameNL
        BLVS    CopyErrorExternal
        EXIT
 ] ; haswipe

        END
